﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Windows.Forms;

namespace SCMS
{
    public abstract class DAO<T> : IDAO<T>
    {
        protected DAOManager mDAOManager;
        protected T mInfo;
        protected bool mIsNewRecord = false;

        public bool IsNewRecord
        {
            get { return mIsNewRecord; }
        }

        public DAOManager DAOManager
        {
            get
            {
                return mDAOManager;
            }
            set { mDAOManager = value; }
        }

        public DbConnection DbConnection
        {
            get
            {
                return mDAOManager.GetDbConnection();
                //return mDbConnection; 
            }
            //set { mDbConnection = value; }
        }

        public DbTransaction DbTransaction
        {
            get
            {
                return mDAOManager.GetDbTransaction();
                //return mDbTransaction; 
            }
            //set { mDbTransaction = value; }
        }

        public T Info
        {
            get { return mInfo; }
            set { mInfo = value; }
        }

        //public V Table
        //{
        //    get { return mTable; }
        //    set { mTable = value; }
        //}

        protected bool IsValidInfo(T aInfo)
        {
            if (aInfo == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Rerive The Field Index in query
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aFieldName"></param>
        /// <returns></returns>

        protected int GetIndex(IDataReader aDbReader, string aFieldName)
        {
            return aDbReader.GetOrdinal(aFieldName);
        }

        /// <summary>
        /// ExecuteReader Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <returns></returns>

        protected IDataReader ExecuteReader(DbCommand aDbCommand)
        {
            if (DbTransaction != null)
            {
                return mDAOManager.GetDataBase().ExecuteReader(aDbCommand, DbTransaction);
            }
            else
            {
                return mDAOManager.GetDataBase().ExecuteReader(aDbCommand);
            }
        }

        /// <summary>
        /// ExecuteNonQuery Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <returns></returns>

        protected int ExecuteNonQuery(DbCommand aDbCommand)
        {
            if (DbTransaction != null)
            {
                return mDAOManager.GetDataBase().ExecuteNonQuery(aDbCommand, DbTransaction);
            }
            else
            {
                return mDAOManager.GetDataBase().ExecuteNonQuery(aDbCommand);
            }
        }

        /// <summary>
        /// ExecuteScalar Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <returns></returns>

        protected object ExecuteScalar(DbCommand aDbCommand)
        {
            if (DbTransaction != null)
            {
                return mDAOManager.GetDataBase().ExecuteScalar(aDbCommand, DbTransaction);
            }
            else
            {
                return mDAOManager.GetDataBase().ExecuteScalar(aDbCommand);
            }
        }

        /// <summary>
        /// ExecuteDataSet Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <returns></returns>

        protected DataSet ExecuteDataSet(DbCommand aDbCommand)
        {
            if (DbTransaction != null)
            {
                return mDAOManager.GetDataBase().ExecuteDataSet(aDbCommand, DbTransaction);
            }
            else
            {
                return mDAOManager.GetDataBase().ExecuteDataSet(aDbCommand);
            }
        }

        /// <summary>
        /// GetSQLStringCommand Helper
        /// </summary>
        /// <param name="aQuery"></param>
        /// <returns></returns>

        protected DbCommand GetSqlStringCommand(string aQuery)
        {
            return mDAOManager.GetDataBase().GetSqlStringCommand(aQuery);
        }

        /// <summary>
        /// LoadDataSet Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <param name="aDataSet"></param>
        /// <param name="aTable"></param>

        protected void LoadDataSet(DbCommand aDbCommand, DataSet aDataSet, string aTable)
        {
            if (DbTransaction != null)
            {
                mDAOManager.GetDataBase().LoadDataSet(aDbCommand, aDataSet, aTable, DbTransaction);
            }
            else
            {
                mDAOManager.GetDataBase().LoadDataSet(aDbCommand, aDataSet, aTable);
            }
        }

        /// <summary>
        /// UpdateDataSet Wrapper
        /// </summary>
        /// <param name="aDataSet"></param>
        /// <param name="aTable"></param>
        /// <param name="aInsertCmd"></param>
        /// <param name="aUpdateCmd"></param>
        /// <param name="aDeleteCmd"></param>
        /// <returns></returns>

        protected int UpdateDataSet(DataSet aDataSet, string aTable, DbCommand aInsertCmd, DbCommand aUpdateCmd, DbCommand aDeleteCmd)
        {
            if (DbTransaction != null)
            {
                return mDAOManager.GetDataBase().UpdateDataSet(aDataSet, aTable, aInsertCmd, aUpdateCmd, aDeleteCmd, DbTransaction);
            }
            else
            {
                return mDAOManager.GetDataBase().UpdateDataSet(aDataSet, aTable, aInsertCmd, aUpdateCmd, aDeleteCmd, UpdateBehavior.Standard);
            }

        }

        /// <summary>
        /// AddInParameter Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <param name="aParaName"></param>
        /// <param name="aDbType"></param>
        /// <param name="aSourceColumn"></param>
        /// <param name="aSourceVersion"></param>

        protected void AddInParameter(DbCommand aDbCommand, string aParaName, DbType aDbType, string aSourceColumn, DataRowVersion aSourceVersion)
        {
            mDAOManager.GetDataBase().AddInParameter(aDbCommand, aParaName, aDbType, aSourceColumn, aSourceVersion);

        }

        /// <summary>
        /// AddInParmeter Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <param name="aParaName"></param>        
        /// <param name="aDbType"></param>

        protected void AddInParameter(DbCommand aDbCommand, string aParaName, DbType aDbType)
        {
            mDAOManager.GetDataBase().AddInParameter(aDbCommand, aParaName, aDbType, aParaName, DataRowVersion.Current);
        }

        /// <summary>
        /// Add In Parameter Helper
        /// </summary>
        /// <param name="aDbCommand"></param>
        /// <param name="aParaName"></param>
        /// <param name="aDbType"></param>
        /// <param name="aValue"></param>

        protected void AddInParameter(DbCommand aDbCommand, string aParaName, DbType aDbType, Object aValue)
        {
            mDAOManager.GetDataBase().AddInParameter(aDbCommand, aParaName, aDbType, aValue);
        }

        /// <summary>
        /// DataReader GetBoolean Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected bool GetBoolean(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetBoolean(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// DataReader GetInt64 Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected long GetInt64(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetInt64(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// GetInt32 Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>
        protected int GetInt32(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetInt32(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// GetInt46 Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected short GetInt16(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetInt16(GetIndex(aDbReader, aField));
        }

        protected byte GetByte(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetByte(GetIndex(aDbReader, aField));
        }

        protected float GetFloat(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetFloat(GetIndex(aDbReader, aField));
        }

        protected float GetSingle(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetFloat(GetIndex(aDbReader, aField));
        }

        //protected byte GetBytes(IDataReader aDbReader, string aField)
        //{
        //    return aDbReader.GetBytes(GetIndex(aDbReader, aField),);
        //}

        /// <summary>
        /// GetString Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected string GetString(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetString(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// GetDecimal Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected decimal GetDecimal(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetDecimal(GetIndex(aDbReader, aField));
        }

        protected double GetDouble(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetDouble(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// GetDateTime Helper
        /// </summary>
        /// <param name="aDbReader"></param>
        /// <param name="aField"></param>
        /// <returns></returns>

        protected DateTime GetDateTime(IDataReader aDbReader, string aField)
        {
            return aDbReader.GetDateTime(GetIndex(aDbReader, aField));
        }

        /// <summary>
        /// SaveDAO Helper
        /// </summary>
        /// <param name="aSQL"></param>
        /// <param name="aTableName"></param>
        /// <returns></returns>

        protected bool SaveDAO(string aSQL, string aTableName)
        {
            DataSet l_dset = new DataSet();
            try
            {
                DbCommand l_select_cmd = GetSqlStringCommand(aSQL);
                LoadDataSet(l_select_cmd, l_dset, aTableName);
                DataTable l_dtable = l_dset.Tables[aTableName];
                if (l_dtable.Rows.Count == 0)
                {
                    DataRow l_drow = l_dtable.NewRow();
                    UpdateRecord(ref l_drow, ref mInfo);
                    l_dtable.Rows.Add(l_drow);
                    mIsNewRecord = true;
                }
                else
                {
                    DataRow l_drow = l_dtable.Rows[0];
                    UpdateRecord(ref l_drow, ref mInfo);
                    mIsNewRecord = false;
                }
                return SaveDataSet(l_dset);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                //ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        /// <summary>
        /// DeleteDAO Helper
        /// </summary>
        /// <param name="aSQL"></param>
        /// <param name="aTableName"></param>
        /// <returns></returns>

        protected bool DeleteDAO(string aSQL, string aTableName)
        {
            try
            {
                DbCommand l_dbcommand = GetSqlStringCommand(aSQL);
                int l_reff = ExecuteNonQuery(l_dbcommand);
                if (l_reff > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                //   ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
            #region "Alternate Format"

            #endregion
        }

        protected T FindDAO(string aSQL)
        {
            try
            {
                DbCommand l_dbcommand = GetSqlStringCommand(aSQL);
                IDataReader l_dbreader = ExecuteReader(l_dbcommand);

                using (l_dbreader)
                {
                    if (l_dbreader.Read())
                    {
                        ReadRecord(ref l_dbreader, ref mInfo);
                    }
                    else
                    {
                        //throw;
                    }
                }
                return mInfo;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                //ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        protected T FindDAO(DbCommand aDbCommand)
        {
            try
            {
                IDataReader l_dbreader = ExecuteReader(aDbCommand);
                using (l_dbreader)
                {
                    if (l_dbreader.Read())
                    {
                        ReadRecord(ref l_dbreader, ref mInfo);
                    }
                    else
                    {
                        // throw;
                    }
                }
                return mInfo;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        protected List<T> FindsDAO(string aSQL)
        {
            List<T> l_list = new List<T>();
            try
            {
                DbCommand l_dbcommand = GetSqlStringCommand(aSQL);
                IDataReader l_dbreader = ExecuteReader(l_dbcommand);

                using (l_dbreader)
                {
                    while (l_dbreader.Read())
                    {
                        T l_info = default(T);
                        ReadRecord(ref l_dbreader, ref l_info);
                        l_list.Add(l_info);
                    }
                }
                return l_list;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        protected List<T> FindsDAO(DbCommand aDBCommand)
        {
            List<T> l_list = new List<T>();
            try
            {
                IDataReader l_dbreader = ExecuteReader(aDBCommand);

                using (l_dbreader)
                {
                    while (l_dbreader.Read())
                    {
                        T l_info = default(T);
                        ReadRecord(ref l_dbreader, ref l_info);
                        l_list.Add(l_info);
                    }
                }
                return l_list;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        protected System.Data.DataSet GetDAODataSet(string aSQL, string aTable)
        {
            DataSet l_dataset = new DataSet();
            try
            {
                DbCommand l_dbcommand = GetSqlStringCommand(aSQL);
                LoadDataSet(l_dbcommand, l_dataset, aTable);
                return l_dataset;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }

        protected System.Data.DataSet GetDAODataSet(DbCommand aCommand, string aTable)
        {
            DataSet l_dataset = new DataSet();
            try
            {
                LoadDataSet(aCommand, l_dataset, aTable);
                return l_dataset;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                //ExceptionPolicy.HandleException(ex, ExceptionPolicy.Policy.DataAccessPolicy);
                throw ex;
            }
        }


        public abstract bool Save();

        public abstract bool Saves(List<T> aList);

        public abstract bool SaveDataSet(System.Data.DataSet aDataSet);

        public abstract bool Delete();

        public abstract T Find();

        public abstract List<T> Finds();

        public abstract System.Data.DataSet GetDataSet();

        protected abstract void UpdateRecord(ref DataRow aDataRow, ref T aInfo);

        protected abstract void ReadRecord(ref IDataReader aDataReader, ref T aInfo);

        #region IDAO<T> Members

        bool IDAO<T>.Save()
        {
            throw new NotImplementedException();
        }

        bool IDAO<T>.Delete()
        {
            throw new NotImplementedException();
        }

        T IDAO<T>.Find()
        {
            throw new NotImplementedException();
        }

        #endregion				
    }
}
